import { GeneratorFactory } from "./GeneratorFactory";

export class GeneratorExecutor {
    constructor() {
        this.reset = false;
        this.gen = null
        this.callback = null
        this.genIndex = 0 //记录状态机执行位置
        this.runAllReadyGen = this.runAllReadyGen.bind(this)
    }

    run(gen, callback,errCallBack) {
        let g = gen;
        this.gen = gen
        this.callback = callback
        let _this = this;
        this.reset = false;
        function next() {
            let result = g.next();
            if (result.done) {
                if (!_this.reset) {//结束的时候检测到暂停状态，不回调
                    callback();
                    return result.value;
                }
            }
            if (!_this.reset) {
                result.value.then(_ => {
                    _this.genIndex++
                    next();
                }).catch(error => {
                    console.log(error);
                    //异常的话，继续向下执行
                    //TODO：失败回调会造成进度条的鬼畜行为，偶发性暂未修复
                    //若检测到存在文件下载错误则直接执行失败回调然后离开状态机
                    // if(errCallBack){
                    //     console.log('下载失败回调');
                    //     errCallBack()
                    //     _this.gen = null
                    //     return 
                    // }
                    next();
                });
            }
        }
        next();
    }

    //运行已经创建好的状态机
    runAllReadyGen() {
        let _this = this;
        function next() {
            let result = _this.gen.next();
            if (result.done) {
                if (!_this.reset) {//结束的时候检测到暂停状态，不回调
                    _this.callback();
                    return result.value;
                }
            }
            if (!_this.reset) {
                result.value.then(_ => {
                    _this.genIndex++
                    next();
                }).catch(error => {
                    console.log(error);
                    //异常的话，继续向下执行
                    _this.genIndex++
                    next();
                });
            }
        }
        next();
    }

    pause() {
        this.reset = true;
    }

    //更新状态机并执行，进来之前一定是先创建新的实例并销毁上一个实例

    upDate(...proArry) {
        let newProArry = []
        let index = 0
        for (let item of this.gen) {
            if (index > this.genIndex) {
                newProArry.push(item)
            }
            index++
        }
        newProArry.unshift(...proArry)
        this.gen = newProArry
        this.genIndex = 0
        return newProArry
    }

    //删除某一个步骤
    deleteOneStep(targetIndex) {
        if (index < this.genIndex) return
        let newGen = []
        let index = 0
        for (item of this.gen) {
            if (index > this.genIndex && index !== targetIndex) {
                newGen.push(item)
            }
            index++
        }
        this.genIndex = 0
        this.gen = new GeneratorFactory(newGen)
    }



    //手动进行下一步操作
    nextStep() {
        if (this.gen) {
            this.gen.next()
        }
    }

    /**
     * 超时继续往下执行,离开本状态机
     * @param gen 状态机
     * @param timeOut 超时时间 单位s
     * @param callback 成功回调
     * @param timeoutCallback 超时回调
     */
    runWithTimeOut(gen, timeOut, callback, timeoutCallback) {
        let g = gen;
        let _this = this;
        this.reset = false;
        function next() {
            let result = g.next();
            if (result.done) {
                if (!_this.reset) {//结束的时候检测到暂停状态，不回调
                    if (callback) {
                        callback();
                    }
                    return result.value;
                }
            }
            if (!_this.reset) {
                let timeoutId = null;
                let timeoutPromise = new Promise((resolve, reject) => {
                    timeoutId = setTimeout(function () {
                        try {
                            if (timeoutCallback) {
                                if(!_this.reset){//超时的时候检测到暂停状态，不回调
                                    console.log("触发超时...")
                                    timeoutCallback();
                                }else{
                                    console.log('超时不触发回调',_this.reset)
                                }
                            }
                        } catch (e) { }
                        resolve("timeout");
                    }, timeOut * 1000);
                });
                Promise.race([result.value, timeoutPromise]).then((value) => {
                    console.log(value);
                    if (value !== "timeout") {//不是超时
                        if (timeoutId) {
                            clearTimeout(timeoutId);
                        }
                        next()
                    } else {
                        _this.reset = true;
                    }
                }).catch(() => { next() })
            }
        }
        next();
    }

    /**
     * 超时继续往下执行，单个状态机内部
     * @param gen
     * @param timeOut 设置的超时时间
     * @param callback
     * @param progressCallback
     */
    runSingleWithTimeOut(gen, timeOut, callback, progressCallback) {
        let g = gen;
        let _this = this;
        this.reset = false;
        let count = 0;

        function next() {
            let result = g.next();
            if (result.done) {
                if (!_this.reset) {//结束的时候检测到暂停状态，不回调
                    if (callback) {
                        callback();
                    }
                    return result.value;
                }
            }
            if (!_this.reset) {
                let timeoutId = null;
                let timeoutPromise = new Promise((resolve, reject) => {
                    timeoutId = setTimeout(function () {
                        console.log("触发超时...")
                        resolve("timeout");
                    }, timeOut * 1000);
                });
                Promise.race([result.value, timeoutPromise]).then((value) => {
                    console.log(value);
                    if (value !== "timeout") {//不是超时
                        if (timeoutId) {
                            clearTimeout(timeoutId);
                        }
                    }
                    count = count + 1;
                    if (progressCallback) {
                        progressCallback(count);
                    }
                    next();
                }).catch(() => { next() })
            }
        }
        next();
    }
}
